/*
============================================================================

Copyright (c) Symbian Ltd 2008. All rights reserved.

 Description 	: CBluetoothConnector has been implemented as a state machine that encapsulates all the BT stack
 				  parts that are responsible for  managing the connection between a Master and a Slave.

				  The CBluetoothConnector's state machine includes the following operations:
				  1) Searching on the remote device (Slave) for available services
				  2) Connecting to the remote device (Slave)
				  3) Both sending and receiving data to/from the remote device (Slave)
				  4) Callbacks to report to the App's engine the state machine error
				     and completion of events such as connection completed, report data, sending data completed.


				  Note that if at any stage we receive an error then the state machine is reset to the EIdle
				  state and all resources previously allocated are closed/cancelled
============================================================================
*/

#ifndef __BLUETOOTHCONNECTOR_H__
#define __BLUETOOTHCONNECTOR_H__

// INCLUDES
#include <bt_sock.h>
#include <btmanclient.h>
#include <btsdp.h>
#include "BluetoothSocketWriterReader.h"
#include "CommonInterfaces.h"

class CBluetoothDeviceDiscoverer;
class CBluetoothServiceSearcher;
class CBluetoothSockConnector;
class CSocketReader;
class CSocketWriter;

/**
* CBluetoothConnector
* Manages the connection between a Master and a Slave
*/
class CBluetoothConnector : public CBluetoothConnectionBase,
							public MBluetoothServiceSearcherObserver,
							public MSocketConnectorObserver,
							public MSocketWriterReaderObserver
    {
public:
	/**
	* TConnectorState
	* State Machine
	*/
	enum TConnectorState
		{
	    EIdle,				//State machine entry point
	    ESearchingService,	//Searching for a service on the remote BT device
	    EConnecting,		//Connecting to the remote BT device
	    EWaitingForData,	//Listening for incoming data
	    ESendingData,		//Sending data to the remote BT device
	    };
public:
	/**
	* Two phase constructor
	* @param aConnObs		Interface to report to the caller the status of the connection and incoming/sending data completion 
	* @param aSocketServer	A handle to an existing session on the socket server (ESock)
	* @param aDevAddr		The remote BT device address
	*/
    static CBluetoothConnector* NewL(MBluetoothObserver& aConnObs, RSocketServ& aSocketServer, const TBTDevAddr& aDevAddr);

	/**
	* Destructor
	*/
    ~CBluetoothConnector();

public:	//From CBluetoothConnectionBase
	/**
	* Sends the data to the remote BT device. On completion calls MBluetoothObserver::SendDataComplete
	* @param aData	A descriptor for the data being sent to the remote BT device
	*/
	void SendData(const TDesC8& aData);

	/**
	* Kicks off the state machine
	*/
	void StartL();

private:
	/**
	* Constructor
	* @param aConnObs		Interface to report to the caller the status of the connection, incoming/sending data completion 
	* @param aSocketServer	A handle to an existing session on the socket server (ESock)
	* @param aDevAddr		The remote BT device address
	*/
    CBluetoothConnector(MBluetoothObserver& aConnObs, RSocketServ& aSocketServer, const TBTDevAddr& aDevAddr);

	/**
	* Second phase constructor 
	*/
    void ConstructL();
    
private:	// From CActive
	/**
	* Handles CBluetoothConnector's state machine completion events
	*/
	virtual void RunL();
	
	/**
	* Cancels all outstanding BT socket operations
	*/
	virtual void DoCancel();
	
	/**
	* Handles a leave occurring in the request completion event handler RunL()
	* @param aError	 The leave code
	* @return TInt	 The default implementation returns aError.A derived class implementation should return KErrNone,
	*				 if it handles the leave; otherwise it should return any suitable value to cause the handling
	*				 of the error to be propagated back to the active scheduler.
	*/
	virtual TInt RunError(TInt aError);
	
	//From MBluetoothServiceSearcherObserver
	/**
	* Callback to notify the caller of the completion of the service search.
	* @param aPort	 When successful it returns the RFCOMM's port
	* @param aError	 KErrNone if successful, otherwise one of the system errors
	*/
	void OnServiceSearchComplete(TInt aPort, TInt aError);

	//From MSocketConnectorObserver
	/**
	* Callback to notify the caller of the completion of the connection to the remote BT device
	* @param aError	 KErrNone if successfully connected, otherwise one of the system errors
	*/
	void OnSockConnectionComplete(TInt aError);

private:	//From MSocketWriterReaderObserver
	/**
	* Callback to notify the caller of the sending data completion
	* @param aError	 KErrNone if succesful, otherwise one of the system errors
	*/
	void WriteComplete(TInt aError);
	
	/**
	* Callback to notify the caller of incoming data from the remote BT device
	* @param aData	 A descriptor for the data being received from the remote BT device
	* @param aError	 KErrNone if succesful, otherwise one of the system errors
	*/
	void ReportData(const TDesC8& aData, TInt aError);
	
	/**
	* Starts a service search request to the remote BT device
	*/
	void SearchServiceL();
	
	/**
	* Starts connecting to the remote device
	*/
	void ConnectDeviceL();
	
	/**
	* Sets the state machine in the listening mode for remote device's incoming data
	*/
	void WaitForData();
	
	/**
	* Cancels all the CBluetoothConnector's active sockets.
	*/
	void CancelSocket();
	
	/**
	* Calls User::RequestComplete on this active object
	*/
	void SelfComplete();
	
private:
	/**
	* A reference to the MBluetoothObserver interface
	*/
	MBluetoothObserver& iConnObs;
	
	/**
	* A handle to an existing session on the socket server (ESock)
	*/
	RSocketServ& iSocketServer;
	
	/**
	* The remote BT device address
	*/
	TBTDevAddr iBtDevAddr;
	
	/**
	* Client endpoint to the RFCOMM protocol
	*/
	RSocket iBtSocket;
	
	/**
	* State Machine
	*/
	TConnectorState iState;
	
	/**
	* Responsible for finding out if a remote BT device supports a specific BT service.
	* Note that CBluetoothServiceSearcher requires a valid BT remote device address. See CBluetoothDeviceDiscoverer.
	*/
	CBluetoothServiceSearcher* iServiceSearcher;
	
	/**
	* Responsible for connecting to the remote device using the RFCOMM transfer protocol.
	*/
	CBluetoothSockConnector* iSocketConnector;
	
	/**
	* RFCOMM's port
	*/
	TInt iPort;
	
	/**
	* Responsible for notifying the connector either when data arrives from the remote device
	* or when a connection error occurs
	*/
	CSocketReader* iBtSocketReader;
	
	/**
	* Responsible for sending data from the connetor to the remote device and notifing the connector when
	* the transfer is completed.
	*/
	CSocketWriter* iBtSocketWriter;

	/**
	* Max number of retries during a connection attempt to the remote BT device
	*/
	TInt iMaxIterConnection;

	/**
	* ETrue if the Connector is connected to the remote BT device 
	*/
	TBool iConnected;
    };

#endif
